package com.dmgis.qxfw.dataservice.businessservice.common.util;

import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

public class WeiXinUtil {

    /**
     * 获取jsapi_ticket
     *
     * @return
     */
    public static JsapiTicket getjsapiTicket() {
        JsapiTicket jsapiTicket = null;
        String accessToken = (String) AccessTokenCache.getInstance().getAcessTokenAndExpiresIn(WXConstants.APPID, WXConstants.APPSECRET).get("access_token");
        String requestUrl = String.format(WXConstants.jsapi_ticket_url, accessToken);//.replace("ACCESS_TOKEN", accessToken);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        //如果请求成功
        if (null != jsonObject) {
            try {
                jsapiTicket = new JsapiTicket();
                if (jsonObject.get("ticket") != null) {
                    jsapiTicket.setJsapiTicket(jsonObject.get("ticket").toString());
                }
                if (jsonObject.get("expires_in") != null) {
                    jsapiTicket.setExpiresIn(Integer.parseInt(jsonObject.get("expires_in").toString()));
                }

            } catch (Exception e) {
                jsapiTicket = null;
            }
        }
        return jsapiTicket;
    }

    /**
     * 获取access_token
     *
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {
        AccessToken accessToken = null;
        String requestUrl = String.format(WXConstants.access_token_url, appid, appsecret);// .replace("APPID", appid).replace("APPSECRET", appsecret);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果请求成功
        if (null != jsonObject && jsonObject.get("access_token") != null) {
            try {
                accessToken = new AccessToken();
                accessToken.setAccess_token(jsonObject.get("access_token").toString());
                accessToken.setExpires_in(jsonObject.get("expires_in").toString());
            } catch (Exception e) {
                accessToken = null;
                // 获取token失败
                e.printStackTrace();
//                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return accessToken;
    }

    /**
     * @param publicid 公众号原始id
     * @param openid   粉丝id
     * @return
     */
    public static WeiXinUser getUserInfo(String publicid, String openid) {
        String accessToken = (String) AccessTokenCache.getInstance().getAcessTokenAndExpiresIn(WXConstants.APPID, WXConstants.APPSECRET).get("access_token");
        String requestUrl = String.format(WXConstants.user_info_url, accessToken, openid);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        WeiXinUser users = new WeiXinUser();
        // 如果请求成功
        if (null != jsonObject) {
            try {
                users.setSubscribe(jsonObject.getInt("subscribe"));
                users.setOpenId(jsonObject.getString("openid"));
                users.setNickName(jsonObject.getString("nickname"));
                users.setSex(jsonObject.getInt("sex"));
                users.setCity(jsonObject.getString("city"));
                users.setProvince(jsonObject.getString("province"));
                users.setCountry(jsonObject.getString("country"));
                users.setHeadimgUrl(jsonObject.getString("headimgurl"));
                users.setCreateDate(new Date(Long.parseLong(jsonObject.getInt("subscribe_time") + "000")));//转换成毫秒
                users.setPublicId(publicid);
                users.setGroupId(jsonObject.getString("groupid"));
            } catch (Exception e) {

            }
        }
        return users;
    }

    /**
     * 重新获取Code,以后面实现带着Code重新跳回目标页面(没有用户授权的，只能获取基本信息（openid））
     *
     * @param url 目标页面
     */
    public static String GetCodeUrl(String url) {
        String CodeUrl = "";
        //对url进行编码
        try {
            url = URLEncoder.encode(url, "utf-8");
            CodeUrl = String.format(WXConstants.snsapi_base_url, WXConstants.APPID, url);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return CodeUrl;
    }

    /**
     * 根据Code获取用户的openid、access_token
     *
     * @param code
     * @return
     */
    public static String GetOauthAccessOpenId(String code) {
        String openid = "";
        try {
            String url = String.format(WXConstants.oauth2_access_token_url, WXConstants.APPID, WXConstants.APPSECRET, code);
            String gethtml = httpRequest(url, "GET", null).toString();
            OAuthToken ac = JsonUtil.jsonStr2Object(gethtml, OAuthToken.class);
            openid = ac.getOpenid();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return openid;
    }

    /**
     * 描述:  发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);

            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

    /**
     * 加载事件信息
     *
     * @param requestXml 响应事件内容xml
     */
    public static WeChatMessage LoadFromXml(String requestXml) {
        WeChatMessage weChatMessage = new WeChatMessage();
        try {
            InputSource in = new InputSource(new StringReader(requestXml));
            in.setEncoding("UTF-8");
            SAXReader reader = new SAXReader();
            Document document;
            document = reader.read(in);
            String msgType = document.selectSingleNode("/xml/MsgType").getText();
            switch (msgType.toLowerCase()) {
                case "text"://文本类型
                    return new TextMessage(document);
                case "event": {//事件类型
                    return new EventMessage(document);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return weChatMessage;
    }
}
